#! /usr/bin/env python


import os,sys
from xml.etree import ElementTree as ET
import struct


class OptionByte(object):
    def __init__(self, filename = 'tools/opt.xml'):
        self.filename = filename
        self.root = ET.parse(filename).getroot()


    def mkoption(self, outfile='build/out/opt.bin'):
        print("Making option bytes")
        if not os.path.exists(os.path.dirname(outfile)):
            print("Create %s dir" % os.path.dirname(outfile))
            os.mkdir(os.path.dirname(outfile))
        if os.path.isfile(self.filename):
            with open(outfile, 'wb') as f:
                for node in self.root:
                    pack_str = ''
                    data     = 0
                    if len(node) == 1 or len(node) == 0:
                        #write single node
                        pack_str = node.attrib['pack']
                        if '0x' in node.attrib['data'] or '0X' in node.attrib['data']:
                            data = int(node.attrib['data'],16)
                        else:
                            data = int(node.attrib['data'])
                        f.write(struct.pack(pack_str, data))
                        if 'comp' in node.attrib:
                            data =  (~data)&(int('FF'*int(node.attrib['size']), 16))
                            f.write(struct.pack(pack_str, data))
                    elif len(node) == 8 or 'data' not in node.attrib:
                        #write 8-bit node or all sub-node
                        data = 0
                        pack_str = node.attrib['pack']
                        for subnode in node:
                            if '0x' in subnode.attrib['data'] or '0X' in subnode.attrib['data']:
                                nodedata = int(subnode.attrib['data'], 16)
                            else:
                                nodedata = int(subnode.attrib['data'])
                            if '0x' in subnode.attrib['offset'] or '0X' in subnode.attrib['offset']:
                                shift = int(subnode.attrib['offset'],16)
                            else:
                                shift = int(subnode.attrib['offset'])
                            if nodedata:
                                data |= nodedata << shift
                        f.write(struct.pack(pack_str, data))
                        if 'comp' in node.attrib:
                            data =  (~data)&(int('FF'*int(node.attrib['size']), 16))
                            f.write(struct.pack(pack_str,data))
                    else:
                        #invalid config
                        print("invalid config for node(%s)" % node.attrib["num"])
